函数
<new>

operator new

throwing (1)
void* operator new (std::size_t size) throw (std::bad_alloc);
nothrow (2)
void* operator new (std::size_t size, const std::nothrow_t& nothrow_value) throw();
placement (3)
void* operator new (std::size_t size, void* ptr) throw();
throwing (1)
void* operator new (std::size_t size);
nothrow (2)
void* operator new (std::size_t size, const std::nothrow_t& nothrow_value) noexcept;
placement (3)
void* operator new (std::size_t size, void* ptr) noexcept;
分配存储空间
默认的分配函数(单对象形式)。

(1)抛出异常的分配
分配 size 字节的存储空间,该空间对任何大小的对象都具有合适的对齐方式,并返回指向此块内存第一个字节的非空指针。
失败时,它会抛出 bad_alloc 异常。
(2)不抛出异常的分配
与上面(1)相同,不同之处在于失败时返回空指针而不是抛出异常。
如果被替换,第一种和第二种版本都应返回具有相同属性的指针。
默认定义通过调用第一个版本来分配内存:::operator new (size)
如果被替换,第一种和第二种版本都应返回具有相同属性的指针。
(3)定位
简单地返回 ptr(不分配任何存储空间)。
但请注意,如果该函数是由new表达式调用的,则会执行正确的初始化(对于类对象,这包括调用其默认构造函数)。

默认的分配和释放函数是标准库的特殊组件;它们具有以下独特属性:
  • 全局:operator new 的所有三个版本都在全局命名空间中声明,而不是在 std 命名空间中。
  • 隐式:分配版本((1)(2))在 C++ 程序的每个翻译单元中都隐式声明,无论是否包含头文件 <new>
  • 可替换:分配版本((1)(2))也可替换:程序可以提供自己的定义来替换默认提供的定义,以产生上述结果,或者可以为特定类型重载它。

如果已使用 set_new_handler 定义了 new_handler 函数,则当分配版本((1)(2))无法分配所需存储空间时,将由这些分配版本的默认定义调用此new-handler 函数。

operator new 可以显式地作为一个常规函数调用,但在 C++ 中,new 是一个具有非常特定行为的运算符:带有 new 运算符的表达式首先用其类型说明符的大小作为第一个参数调用函数 operator new(即此函数),如果成功,则自动初始化或构造对象(如果需要)。最后,该表达式求值为指向相应类型的指针。

参数

size
请求内存块的大小(以字节为单位)。
当由new表达式自动调用时,这是类型说明符的大小。
如果此参数为零,则函数成功时仍返回一个不同的非空指针(尽管解引用此指针会导致未定义行为)。
size_t 是一个整型。
nothrow_value
常量 nothrow
此参数仅用于将其与具有重载版本的第一个版本区分开。当 nothrow 常量作为第二个参数传递给 operator new 时,operator new 在失败时返回空指针,而不是抛出 bad_alloc 异常。
nothrow_t 是常量 nothrow 的类型。
ptr
指向已分配的、大小合适的内存块的指针。
如果由new表达式调用,则在该位置初始化(或构造)对象。

返回值

对于第一和第二个版本,指向新分配的存储空间的指针。
对于第三个版本,返回 ptr

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// operator new example
#include <iostream>     // std::cout
#include <new>          // ::operator new

struct MyClass {
  int data[100];
  MyClass() {std::cout << "constructed [" << this << "]\n";}
};

int main () {

  std::cout << "1: ";
  MyClass * p1 = new MyClass;
      // allocates memory by calling: operator new (sizeof(MyClass))
      // and then constructs an object at the newly allocated space

  std::cout << "2: ";
  MyClass * p2 = new (std::nothrow) MyClass;
      // allocates memory by calling: operator new (sizeof(MyClass),std::nothrow)
      // and then constructs an object at the newly allocated space

  std::cout << "3: ";
  new (p2) MyClass;
      // does not allocate memory -- calls: operator new (sizeof(MyClass),p2)
      // but constructs an object at p2

  // Notice though that calling this function directly does not construct an object:
  std::cout << "4: ";
  MyClass * p3 = (MyClass*) ::operator new (sizeof(MyClass));
      // allocates memory by calling: operator new (sizeof(MyClass))
      // but does not call MyClass's constructor

  delete p1;
  delete p2;
  delete p3;

  return 0;
}

可能的输出

1: constructed [0x8f0f70]
2: constructed [0x8f23a8]
3: constructed [0x8f23a8]
4: 


数据竞争

修改返回的值所引用的存储。
分配和释放函数的调用,如果重用了相同的存储单元,则应以单一的总顺序进行,其中每次释放都完全发生在下次分配之前。
这也应适用于此函数的自定义替换的可观察行为。

异常安全

第一个版本(1) 在无法分配存储空间时抛出 bad_alloc
否则,它不抛出任何异常(无异常保证)。

另见